#ifndef MATH_MATRIX_MATRIX
#define MATH_MATRIX_MATRIX

#include <iostream>

#include "Vector.hpp"
#include "predefmatrix.hpp"


namespace Math
{




    
template <typename T, typename K = T>
class Matrix;

template <typename T, typename K>
Matrix<T,K> operator*(const K& left, const Matrix<T,K>& right);  // number * matrix

template <typename T, typename K>
ostream& operator<<(ostream& output, const Matrix<T,K>& rgiht);



template <typename T, typename K>
class Matrix
    {
        public:
            virtual ~Matrix() { DeleteSpace(); } 
            Matrix(); // zero matrix
            Matrix(const Matrix<T,K>& copy);
            Matrix(Matrix<T,K>&& move);
            Matrix(const T* const _matrix);

            void               MT();
            void               LoadIdentityMatrix();
            void               FillMatrix(const T w);
            inline void        LoadZeroMatrix(); 

            const  Matrix<T,K>& operator=(Matrix<T,K>&& left);       // matrix = matrix
            const  Matrix<T,K>& operator=(const Matrix<T,K>& left);  // matrix = matrix
                   Vector<T,K>& operator[](ushorti index);
            const  Vector<T,K>& operator[](ushorti index) const;
                   Matrix<T,K>  operator*(const K& right) const;           // matrix * number
                   Matrix<T,K>  operator*(const Matrix<T,K>& right) const; // matrix * matrix
                   Matrix<T,K>  operator+(const Matrix<T,K>& right) const;  // matrix + Matrix

            friend Matrix<T,K> (Math::operator*<>)(const K& left, const Matrix<T,K>& right);
            friend ostream&    (Math::operator<<<>)(ostream& output, const Matrix<T,K>& right);


        protected:
            void        CreateColumnSpace();
            void        CreateLinesSpace(const T* const marix);
            inline void CopyColumnSpace(Vector<T,K>** new_space) const;
            inline void CopyLinesSpace(Vector<T,K>** new_space) const;
            void        DeleteSpace();


        private:
            Vector<T,K>** Getcolumn_space()  const   { return column_space; }
            Vector<T,K>** Getlines_space()   const   { return lines_space; }

            Vector<T,K>** lines_space;
            Vector<T,K>** column_space; 
    };
} // end namespace Math

#include "error/Throw_Matrix.hpp"
#include "source/Matrix.cpp"

#endif
